package com.pai4j.message.core.builder;
import com.pai4j.common.enums.InteractionMessageTypeEnum;
import com.pai4j.common.enums.community.ResourceTypeEnum;
import com.pai4j.domain.vo.dto.BaseMessageDTO;
import com.pai4j.message.core.interceptor.InterceptorChain;
import com.pai4j.message.core.provider.ResourceProvider;
import com.pai4j.message.core.provider.ResourceRegistry;
import com.pai4j.message.core.sender.MessageSender;
import com.pai4j.message.core.template.TemplateEngine;
import com.pai4j.message.factory.MessageSenderFactory;
import com.pai4j.message.factory.TemplateEngineFactory;
import com.pai4j.message.model.MessageContext;
import com.pai4j.message.model.ResourceInfo;
import com.pai4j.message.model.SendResult;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.CompletableFuture;

/**
 * 消息构建器抽象基类
 * 实现通用的构建逻辑，子类只需实现特定的业务逻辑
 *
 * <p><b>线程安全说明：</b></p>
 * <ul>
 *   <li>MessageBuilder <b>不是线程安全的</b>，不应在多线程间共享实例</li>
 *   <li>每次使用请创建新的Builder：{@code MessageFacade.interaction().like()}</li>
 *   <li>不要将Builder实例存储为字段或单例使用</li>
 *   <li>多线程发送消息时，每个线程应创建独立的Builder实例</li>
 * </ul>
 *
 * <p><b>正确用法：</b></p>
 * <pre>{@code
 * // 正确：每次都创建新Builder
 * MessageFacade.interaction().like()
 *     .sender(userId)
 *     .resource(ResourceTypeEnum.ARTICLE, articleId)
 *     .send();
 * }</pre>
 *
 * <p><b>错误用法：</b></p>
 * <pre>{@code
 * // 错误：不要重用Builder实例
 * LikeMessageBuilder builder = MessageFacade.interaction().like();
 * builder.sender(user1).send();  // 第一次使用
 * builder.sender(user2).send();  // 错误！会携带第一次的状态
 * }</pre>
 *
 * @author PAI4J Team
 * @date 2025-11-01
 * @param <T> 消息DTO类型
 */
@Slf4j
public abstract class AbstractMessageBuilder<T extends BaseMessageDTO> implements MessageBuilder<T> {

    /**
     * 消息上下文
     */
    protected MessageContext context;

    /**
     * 拦截器链
     * -- SETTER --
     *  设置拦截器链
     
     */
    @Setter
    protected InterceptorChain interceptorChain;

    /**
     * 构造函数
     */
    protected AbstractMessageBuilder() {
        this.context = MessageContext.builder()
                .metadata(new HashMap<>())
                .build();
    }
    
    @Override
    public MessageBuilder<T> sender(String senderId) {
        context.setSenderId(senderId);
        return this;
    }

    @Override
    public MessageBuilder<T> receiver(String receiverId) {
        context.setReceiverId(receiverId);
        return this;
    }

    @Override
    public MessageBuilder<T> messageType(InteractionMessageTypeEnum type) {
        context.setMessageTypeEnum(type);
        context.setType(type.name());
        return this;
    }

    @Override
    public MessageBuilder<T> resource(ResourceTypeEnum resourceType, String resourceId) {
        return resource(resourceType.getType(), resourceId);
    }

    @Override
    public MessageBuilder<T> resource(String resourceType, String resourceId) {
        context.setResourceType(resourceType);
        context.setResourceId(resourceId);
        
        // 自动填充资源信息
        fillResourceInfo();
        
        return this;
    }

    @Override
    public MessageBuilder<T> content(String content) {
        context.setContent(content);
        return this;
    }

    @Override
    public MessageBuilder<T> template(String templateCode, Object... vars) {
        context.setTemplateCode(templateCode);
        context.setTemplateVars(vars);
        
        // 渲染模板
        renderTemplate();
        
        return this;
    }

    @Override
    public MessageBuilder<T> commentId(Long commentId) {
        context.setCommentId(commentId);
        return this;
    }

    @Override
    public MessageBuilder<T> replyId(Long replyId) {
        context.setReplyId(replyId);
        return this;
    }

    @Override
    public MessageBuilder<T> metadata(String key, Object value) {
        context.addMetadata(key, value);
        return this;
    }

    @Override
    public MessageBuilder<T> channels(String... channels) {
        context.setChannels(channels);
        return this;
    }

    @Override
    public MessageBuilder<T> async() {
        context.setAsync(true);
        return this;
    }

    @Override
    public MessageBuilder<T> sync() {
        context.setAsync(false);
        return this;
    }

    @Override
    public MessageBuilder<T> priority(int priority) {
        context.setPriority(Math.max(1, Math.min(10, priority)));
        return this;
    }

    @Override
    public MessageBuilder<T> skipInterceptors() {
        context.setSkipInterceptors(true);
        return this;
    }

    @Override
    public T build() {
        // 验证必填字段
        if (!validate()) {
            throw new IllegalStateException("消息构建失败：必填字段未设置");
        }

        // 创建消息DTO
        T messageDTO = createMessageDTO();
        
        // 填充基础字段
        messageDTO.setCategory(getMessageCategory());
        messageDTO.setType(context.getType());
        messageDTO.setFromUserId(context.getSenderId());
        messageDTO.setToUserId(context.getReceiverId());
        messageDTO.setContent(context.getContent());
        messageDTO.setCreateDate(new Date());
        messageDTO.setIsRead(false);

        // 填充扩展字段
        fillMessageDTO(messageDTO);

        // 保存到上下文
        context.setMessageDTO(messageDTO);

        return messageDTO;
    }

    @Override
    public SendResult send() {
        // 构建消息
        T messageDTO = build();

        // 执行拦截器
        if (interceptorChain != null && !interceptorChain.doIntercept(context)) {
            return SendResult.failure("INTERCEPTED", "消息被拦截器拦截", "unknown");
        }

        // 发送消息
        SendResult result = doSend(messageDTO);

        log.info("消息发送完成: success={}, channel={}", result.isSuccess(), result.getChannel());

        return result;
    }

    @Override
    public CompletableFuture<SendResult> sendAsync() {
        return CompletableFuture.supplyAsync(this::send);
    }

    @Override
    public boolean validate() {
        // 基础验证
        if (StringUtils.isBlank(context.getSenderId())) {
            log.warn("消息发送者不能为空");
            return false;
        }
        if (StringUtils.isBlank(context.getReceiverId())) {
            log.warn("消息接收者不能为空");
            return false;
        }
        
        // 子类自定义验证
        return doValidate();
    }

    @Override
    public MessageBuilder<T> reset() {
        this.context = MessageContext.builder()
                .metadata(new HashMap<>())
                .build();
        return this;
    }

    @Override
    public MessageBuilder<T> activity(String activityName, String activityUrl) {
        context.setActivityName(activityName);
        context.setActivityUrl(activityUrl);
        return this;
    }

    /**
     * 填充资源信息
     */
    protected void fillResourceInfo() {
        if (StringUtils.isBlank(context.getResourceType()) || 
            StringUtils.isBlank(context.getResourceId())) {
            return;
        }

        try {
            ResourceProvider provider = ResourceRegistry.getProvider(context.getResourceType());
            if (provider != null) {
                ResourceInfo resourceInfo = provider.getResourceInfo(context.getResourceId());
                if (resourceInfo != null) {
                    context.setResourceInfo(resourceInfo);
                    
                    // 自动设置接收者（如果未设置）
                    if (StringUtils.isBlank(context.getReceiverId()) && 
                        StringUtils.isNotBlank(resourceInfo.getOwnerId())) {
                        context.setReceiverId(resourceInfo.getOwnerId());
                    }
                }
            }
        } catch (Exception e) {
            log.warn("填充资源信息失败: resourceType={}, resourceId={}, error={}", 
                    context.getResourceType(), context.getResourceId(), e.getMessage());
        }
    }

    /**
     * 渲染模板
     */
    protected void renderTemplate() {
        if (StringUtils.isBlank(context.getTemplateCode())) {
            return;
        }

        try {
            TemplateEngine engine = TemplateEngineFactory.getEngine();
            if (engine != null) {
                String template = context.getTemplateCode();
                String[] varNames = getTemplateVarNames();
                Object[] varValues = context.getTemplateVars();
                
                String content = engine.render(template, varNames, varValues);
                context.setContent(content);
            }
        } catch (Exception e) {
            log.warn("渲染模板失败: templateCode={}, error={}", 
                    context.getTemplateCode(), e.getMessage());
        }
    }

    /**
     * 执行发送
     */
    protected SendResult doSend(T messageDTO) {
        String[] channels = context.getChannels();
        if (channels == null || channels.length == 0) {
            channels = new String[]{"message-queue"};
        }

        // 使用第一个可用的发送器
        for (String channel : channels) {
            try {
                MessageSender sender = MessageSenderFactory.getSender(channel);
                if (sender != null && sender.isAvailable()) {
                    return sender.send(context);
                }
            } catch (Exception e) {
                log.error("发送消息失败: channel={}, error={}", channel, e.getMessage(), e);
            }
        }

        return SendResult.failure("NO_SENDER", "没有可用的发送器", "unknown");
    }

    /**
     * 获取消息分类
     */
    protected abstract String getMessageCategory();

    /**
     * 创建消息DTO对象
     */
    protected abstract T createMessageDTO();

    /**
     * 填充消息DTO（子类扩展）
     */
    protected abstract void fillMessageDTO(T messageDTO);

    /**
     * 自定义验证逻辑（子类扩展）
     */
    protected boolean doValidate() {
        return true;
    }

    /**
     * 获取模板变量名数组（子类扩展）
     */
    protected String[] getTemplateVarNames() {
        return new String[0];
    }
}

